hpr3107 :: Generating comfortable passwords
Audio With External Links Item Preview
Share or Embed This Item
Source: http://hackerpublicradio.org/eps.php?id=3107
Original audio: http://archive.org/download/hpr3107/hpr3107_source.ogg
Random Password Generation
First implementation: 14 character long with 6 letters and 8 digits
#!/usr/bin/env python3
# file: passgen-v1.py
import random
LETTERS = "abcdefghijklmnopqrstuvwxyz"
if __name__ == "__main__":
passwd = []
for i in range(6):
passwd.append(random.choice(LETTERS))
for i in range(8):
passwd.append(random.choice("1234567890"))
print("".join(passwd))
The passwords that come out of this are a bit difficult to type so I forced it to alternate between the left and right hands
#!/usr/bin/env python3
# file: passgen-v2.py
import random
LEFTS = "',.pyaoeui;qjkx"
RIGHTS = "fgcrldhdhtns-bmwvz"
if __name__ == "__main__":
passwd = []
for i in range(6):
if i % 2 == 0:
passwd.append(random.choice(LEFTS))
else:
passwd.append(random.choice(RIGHTS))
for i in range(8):
if i % 2 == 0:
passwd.append(random.choice("123456"))
else:
passwd.append(random.choice("7890"))
print("".join(passwd))
The regularity of switching between left and right hands (intuitively, and almost surely) decreases the entropy of the password, so use markov models to make that happen for the most part but critically NOT enforce it.
#!/usr/bin/env python3
# file: passgen-v3.py
import random
Ls = [
"aoeui", # L1
"',.py", # L2
";qjkx", # L3
"123456", # L4
"-snthd", # R1
"lrcgf", # R2
"zvwmb", # R3
"7890" # R4
]
A = [[ .03, .03, .03, .01, .27, .27, .27, .09],
[ .03, .03, .03, .01, .27, .27, .27, .09],
[ .03, .03, .03, .01, .27, .27, .27, .09],
[.004, .003, .003, .09, .03, .03, .03, .81],
[ .27, .27, .27, .09, .03, .03, .03, .01],
[ .27, .27, .27, .09, .03, .03, .03, .01],
[ .27, .27, .27, .09, .03, .03, .03, .01],
[ .03, .03, .03, .81, .004, .003, .003, .09]]
pi = [ .41, .03, .03, .03, .41, .03, .03, .03]
def sample( l ):
l_partial = [ sum(l[:i+1],0) for i in range(len(l))]
u = random.uniform(0,1)
for j,v in enumerate(l_partial):
if v > u:
return j
if __name__ == "__main__":
passwd = []
s = sample(pi)
for i in range(20):
s = sample(A[s])
passwd.append(random.choice(Ls[s]))
print("".join(passwd))
For increased entropy should also consider peppering in a few upper case characters.
#!/usr/bin/env python3
# file: passgen-v3.py
import random
Ls = [
"aoeui", # L1
"',.py", # L2
";qjkx", # L3
"123456", # L4
"-snthd", # R1
"lrcgf", # R2
"zvwmb", # R3
"7890" # R4
]
A = [[ .03, .03, .03, .01, .27, .27, .27, .09],
[ .03, .03, .03, .01, .27, .27, .27, .09],
[ .03, .03, .03, .01, .27, .27, .27, .09],
[.004, .003, .003, .09, .03, .03, .03, .81],
[ .27, .27, .27, .09, .03, .03, .03, .01],
[ .27, .27, .27, .09, .03, .03, .03, .01],
[ .27, .27, .27, .09, .03, .03, .03, .01],
[ .03, .03, .03, .81, .004, .003, .003, .09]]
pi = [ .41, .03, .03, .03, .41, .03, .03, .03]
UPPER=.1
def sample( l ):
l_partial = [ sum(l[:i+1],0) for i in range(len(l))]
u = random.uniform(0,1)
for j,v in enumerate(l_partial):
if v > u:
return j
if __name__ == "__main__":
passwd = []
s = sample(pi)
for i in range(20):
s = sample(A[s])
c = random.choice(Ls[s])
u = random.uniform(0,1)
if u < UPPER:
c = c.upper()
passwd.append(c)
print("".join(passwd))
Finally, generating the matrix by hand was a bit of a pain, so I made it a bit easier by making a small procedure with few control knobs (the variables SWITCH_HAND
and SWITCH_CHAR
which control how likely it is that a character pair will result in a hand switch, or a switch between general characters and digits).
#!/usr/bin/env python3
import random
import numpy
# this version uses a markov chain to make it more likely to alternate hands
# (in dvorak) so that the password is easy to type (in dvorak)
Ls = [
"aoeui", # L1
"',.py", # L2
";qjkx", # L3
"123456", # L4
"-snthd", # R1
"lrcgf", # R2
"zvwmb", # R3
"7890" # R4
]
SWITCH_HAND = .8
SWITCH_CHAR = .3
UPPER=.1
def prob( i , j ):
switch_hand = int(i / 4) != int(j / 4)
to_num = (j % 4) == 3
from_num = (i % 4) == 3
prob = 1
if to_num and from_num:
prob *= (1 - SWITCH_CHAR)
elif to_num:
prob *= (SWITCH_CHAR)
elif from_num:
prob *= (SWITCH_CHAR / 3)
else:
prob *= ((1 - SWITCH_CHAR) / 3)
if switch_hand:
prob *= SWITCH_HAND
else:
prob *= (1 - SWITCH_HAND)
return prob
A = numpy.array([ [ prob(i,j) for j in range(8) ] for i in range(8) ])
pi = [ 1.0 / 8 for i in range(8) ]
def sample( l ):
l_partial = [ sum(l[:i+1],0) for i in range(len(l))]
u = random.uniform(0,1)
for j,v in enumerate(l_partial):
if v > u:
return j
if __name__ == "__main__":
passwd = []
s = sample(pi)
for i in range(20):
s = sample(A[s])
c = random.choice(Ls[s])
u = random.uniform(0,1)
if u < UPPER:
c = c.upper()
passwd.append(c)
print("".join(passwd))
- Addeddate
- 2020-06-27 11:18:52
- Identifier
- hpr3107
- Scanner
- Internet Archive Python library 1.9.3
comment
Reviews
1,958 Views
DOWNLOAD OPTIONS
IN COLLECTIONS
Hacker Public Radio PodcastsUploaded by HackerPublicRadio on